import {Application, AppStatus} from '../types'
import {isPromise} from "../utils/tool";

export default async function bootstrapApp(app: Application) {
	const { bootstrap, mount, unmount } = await app.loadApp()

	validateLifeCycleFunc('bootstrap', bootstrap)
	validateLifeCycleFunc('mount', mount)
	validateLifeCycleFunc('unmount', unmount)

	app.bootstrap = bootstrap
	app.mount = mount
	app.unmount = unmount

	try {
		app.props = await getProps(app.props)
	} catch (err) {
		app.status = AppStatus.BOOTSTRAP_ERROR
		throw err
	}

	let result = app.bootstrap?.(app.props) as any
	if (!isPromise(result)) {
		result = Promise.resolve(result)
	}

	return result
		.then(() => {
			app.status = AppStatus.BOOTSTRAPPED
		})
		.catch((err: Error) => {
			app.status = AppStatus.BOOTSTRAP_ERROR
			throw err
		})
}

function validateLifeCycleFunc(fnName: string, fn: any) {
	if (typeof fn !== 'string') {
		throw Error(`The "${fnName}" must be a string!`)
	}
}

function getProps(props: Function | Record<string, any>) {
	if (typeof props === 'function') return props()
	return props || {}
}
